// import { app } from "electron";
import path from "path";
import fs from "fs";
import * as p_fs from "fs/promises";
import crypto from "crypto";

/**
 * 数据文件存储路径
 * @constant {string} filePath - 用户数据存储目录
 */
// const filePath = app.getPath("userData");
const filePath = "C:\\Users\\Administrator\\AppData\\Roaming\\my_Tools";
const saltFilePath = path.join(filePath, "salt.bin");
const keyFilePath = path.join(filePath, "key.bin");
const pwdFilePath = path.join(filePath, "pwd.bin");
const saltLength = 16;
const keyLength = 32;
const ivLength = 16;
const saltNum = 1000;

/**
 * 保存文件到指定路径
 * @param {string} [url] - 文件路径
 * @param {Buffer} buffer - 要保存的二进制数据
 * @param {string} [pathStr] - 预定义路径类型('salt'/'key'/'pwd')
 * @returns {boolean|null} - 保存成功返回true，失败返回null
 */
const saveFile = (url, buffer, pathStr) => {
	try {
		if (!url) {
			if (pathStr && pathStr == "salt") {
				url = saltFilePath;
			} else if (pathStr && pathStr == "key") {
				url = keyFilePath;
			} else if (pathStr && pathStr == "pwd") {
				url = pwdFilePath;
			} else {
				return null;
			}
		}
		// 检查文件是否存在
		if (fs.existsSync(url)) {
			console.log("文件已存在");
			return null;
		}
		// 确保目录存在
		fs.mkdirSync(path.dirname(url), { recursive: true });

		// 写入文件（二进制模式）
		fs.writeFileSync(url, buffer);
		return true;
	} catch (err) {
		return null;
	}
};

/**
 * 从指定路径读取文件数据
 * @param {string} [url] - 文件路径
 * @param {string} [pathStr] - 预定义路径类型('salt'/'key'/'pwd')
 * @returns {Buffer|null} - 读取成功返回Buffer数据，失败返回null
 */
const getData = (url, pathStr) => {
	try {
		if (!url) {
			if (pathStr && pathStr == "salt") {
				url = saltFilePath;
			} else if (pathStr && pathStr == "key") {
				url = keyFilePath;
			} else if (pathStr && pathStr == "pwd") {
				url = pwdFilePath;
			} else {
				return null;
			}
		}
		const data = fs.readFileSync(url);
		return data;
	} catch (err) {
		console.error("读取文件失败:", err);
		return null;
	}
};

/**
 * 删除指定路径的文件
 * @param {string} [url] - 文件路径
 * @param {string} [pathStr] - 预定义路径类型('salt'/'key'/'pwd')
 * @returns {boolean} - 删除成功返回true，失败返回false
 */
const delFile = (url, pathStr) => {
	try {
		if (!url) {
			if (pathStr && pathStr == "salt") {
				url = saltFilePath;
			} else if (pathStr && pathStr == "key") {
				url = keyFilePath;
			} else if (pathStr && pathStr == "pwd") {
				url = pwdFilePath;
			} else {
				return false;
			}
		}
		if (fs.existsSync(url)) {
			fs.unlinkSync(url);
			return true;
		}
		return true;
	} catch (err) {
		return false;
	}
};

/**
 * 确保salt文件存在，不存在则创建
 * @returns {void}
 */
const ensureSaltExists = () => {
	// 生成随机盐值（16字节）
	const salt = crypto.randomBytes(saltLength);
	// 保存Salt文件
	saveFile(saltFilePath, salt);
};

/**
 * 使用问题和答案生成加密密钥
 * @param {string} Q1_answer - 第一个问题的答案
 * @param {string} Q2_answer - 第二个问题的答案
 * @returns {Buffer|null} - 返回包含key和iv的Buffer，失败返回null
 */
const encryptAnswer = (Q1_answer, Q2_answer) => {
	try {
		// 读取盐值
		const salt = getData(saltFilePath);
		if (!salt) {
			return null;
		}
		// 派生 Key 和 IV
		const key = crypto.pbkdf2Sync(
			Q1_answer,
			salt,
			saltNum,
			keyLength,
			"sha256"
		);
		const iv = crypto.pbkdf2Sync(Q2_answer, salt, saltNum, ivLength, "sha256");
		const keyIvBuffer = Buffer.concat([key, iv]);
		return keyIvBuffer;
	} catch (error) {
		return null;
	}
};

/**
 * 验证加密文件的存在性和有效性
 * @returns {Promise<Object>} - 返回验证结果对象
 * @property {Object} exists - 文件存在状态
 * @property {Object} isValid - 文件有效性状态
 * @property {boolean} allExist - 所有文件都存在
 * @property {boolean} allValid - 所有文件都有效
 */
const validateEncryptionFiles = async () => {
	// 检查文件是否存在并读取内容
	const [saltContent, keyContent, pwdContent] = await Promise.all([
		p_fs.readFile(saltFilePath).catch(err => null), // 如果文件不存在，返回 null
		p_fs.readFile(keyFilePath).catch(err => null),
		p_fs.readFile(pwdFilePath).catch(err => null),
	]);

	// 验证文件是否存在
	const exists = {
		salt: saltContent !== null,
		key: keyContent !== null,
		pwd: pwdContent !== null,
	};

	// 验证文件内容是否有效
	const isValid = {
		salt: false,
		key: false,
		pwd: false,
	};
	// 验证 salt.bin（应该是字符串或可转换为字符串的 Buffer）
	if (exists.salt) {
		try {
			const saltStr = saltContent.toString("hex");
			isValid.salt = saltStr.length === saltLength * 2; // 非空字符串
		} catch (err) {
			isValid.salt = false;
		}
	}

	// 验证 key.bin（应该是数组或可解析为数组的 Buffer）
	if (exists.key) {
		try {
			const keyPart = keyContent.slice(0, 32); // 前 32 字节是 key
			const ivPart = keyContent.slice(32); // 后 16 字节是 iv
			isValid.key =
				keyPart.toString("hex").length === keyLength * 2 &&
				ivPart.toString("hex").length === ivLength * 2;
		} catch (err) {
			isValid.key = false;
		}
	}

	// 验证 pwd.bin（应该是字符串或可转换为字符串的 Buffer）
	if (exists.pwd) {
		try {
			const pwdStr = pwdContent.toString("hex");
			isValid.pwd = pwdStr.trim().length > 0; // 非空字符串
		} catch (err) {
			isValid.pwd = false;
		}
	}

	// 返回综合结果
	return {
		exists,
		isValid,
		allExist: exists.salt && exists.key && exists.pwd,
		allValid: isValid.salt && isValid.key && isValid.pwd,
	};
};

/**
 * AES-256-CBC加密
 * @param {string} text - 要加密的文本
 * @param {Buffer} key - 加密密钥
 * @param {Buffer} iv - 初始化向量
 * @returns {Buffer|null} - 加密后的Buffer数据，失败返回null
 */
const encrypt = (text, key, iv) => {
	try {
		const cipher = crypto.createCipheriv("aes-256-cbc", key, iv);
		let encrypted = Buffer.concat([
			cipher.update(text, "utf8"), // 返回 Buffer
			cipher.final(), // 返回 Buffer
		]);
		return encrypted;
	} catch (e) {
		return null;
	}
};

/**
 * AES-256-CBC解密
 * @param {Buffer} encryptedText - 要解密的Buffer数据
 * @param {Buffer} key - 解密密钥
 * @param {Buffer} iv - 初始化向量
 * @returns {Buffer|undefined} - 解密后的Buffer数据，失败返回undefined
 */
const decrypt = (encryptedText, key, iv) => {
	try {
		const decipher = crypto.createDecipheriv("aes-256-cbc", key, iv);
		let decrypted = Buffer.concat([
			decipher.update(encryptedText), // 解密主体（Buffer）
			decipher.final(), // 解密最后一块（Buffer）
		]);
		return decrypted;
	} catch (e) {
		console.log(e);
	}
};

/**
 * 比较两个Buffer是否相等(恒定时间比较)
 * @param {Buffer} buf1 - 第一个Buffer
 * @param {Buffer} buf2 - 第二个Buffer
 * @returns {boolean} - 相等返回true，否则返回false
 */
const areBuffersEqual = (buf1, buf2) => {
	// 检查输入有效性
	if (!buf1 || !buf2) return false;
	if (buf1 === buf2) return true; // 同一引用直接返回true

	// 统一转换为Uint8Array视图以便跨类型比较
	const a = new Uint8Array(buf1);
	const b = new Uint8Array(buf2);

	// 长度不同直接返回false
	if (a.length !== b.length) return false;

	// 恒定时间比较（防止时序攻击）
	let result = 0;
	for (let i = 0; i < a.length; i++) {
		result |= a[i] ^ b[i]; // 异或操作，不同字节会使result变为非0
	}

	return result === 0;
};

export {
	saveFile,
	delFile,
	getData,
	ensureSaltExists,
	encryptAnswer,
	validateEncryptionFiles,
	encrypt,
	decrypt,
	areBuffersEqual
};